package com.jin.webvideo.base.util;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

public class ReflectUtil {
    /**
     * 转换为Array
     * @param obj
     * @return
     * @throws ReflectiveOperationException
     */
    public static Object toArray(Object obj) throws ReflectiveOperationException {
        if (obj == null) {
            throw new ReflectiveOperationException("obj is null");
        }
        Class<?> clazz = obj.getClass();
        if (clazz.isArray()) {
            return obj;
        }
        if (Collection.class.isAssignableFrom(clazz) || obj instanceof Collection) {
            return ((Collection)obj).toArray();
        }
        Object arr = Array.newInstance(clazz, 1);
        Array.set(arr, 0, obj);
        return arr;
    }

    public static Map<String, Object> toMap(Object obj) throws ReflectiveOperationException {
        if (obj == null) {
            throw new ReflectiveOperationException("obj is null");
        }
        Map<String, Object> result = new HashMap<>();
        Class<?> clazz = obj.getClass();
        // Map处理key
        if (Map.class.isAssignableFrom(clazz)) {
            Map<Object, Object> map = (Map<Object, Object>) obj;
            Iterator<Object> iterator = map.keySet().iterator();
            while (iterator.hasNext()) {
                Object key = iterator.next();
                result.put(String.valueOf(key), map.get(key));
            }
            return result;
        }

        // 数组idx作为key
        if (clazz.isArray()) {
            int len = Array.getLength(obj);
            for (int  i = 0; i < len; i++) {
                result.put(String.valueOf(i), Array.get(obj, i));
            }
            return result;
        }

        // 列表顺序作为key
        if (Collection.class.isAssignableFrom(clazz) || obj instanceof Collection) {
            int i = 0;
            Iterator<Object> iterator = ((Collection)obj).iterator();
            while (iterator.hasNext()) {
                Object temp = iterator.next();
                result.put(String.valueOf(i++), temp);
            }
            return result;
        }

        // 其他对象使用get方法
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 0, l = fields.length; i < l; i++) {
            Field field = fields[i];
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            String name = field.getName();
            String getMethodName = "get" + name.substring(0, 1).toUpperCase(Locale.ROOT) + name.substring(1);
            Method method = clazz.getMethod(getMethodName);
            if (method != null) {
                result.put(name, method.invoke(obj));
            }
        }
        return result;
    }
    /**
     * 转化为list
     * @param obj
     * @return
     * @throws ReflectiveOperationException
     */
    public static Object toList(Object obj) throws ReflectiveOperationException {
        if (obj == null) {
            throw new ReflectiveOperationException("obj is null");
        }
        Class<?> clazz = obj.getClass();
        if (clazz.isArray()) {
            int len = Array.getLength(obj);
            List list = new ArrayList(len);
            for (int i = 0; i < len; i++) {
                list.add(Array.get(obj, i));
            }
            return list;
        }
        if (Collection.class.isAssignableFrom(clazz) || obj instanceof Collection) {
            return ((Collection) obj).stream().toList();
        }
        List list = new ArrayList(1);
        list.add(obj);
        return list;
    }

    public static<T> T setField(T obj, String fieldName, Object value) throws ReflectiveOperationException {
        if (obj == null) {
            throw new ReflectiveOperationException("obj is null");
        }
        Field field = obj.getClass().getDeclaredField(fieldName);
        if (!Modifier.isPublic(field.getModifiers())) {
            field.setAccessible(true);
            field.set(obj, value);
            field.setAccessible(false);
        }
        return obj;
    }
    public static void setStaticField(Class clazz, String fieldName, Object value) throws ReflectiveOperationException {
        Field field = clazz.getField(fieldName);
        if (!Modifier.isPublic(field.getModifiers())) {
            field.setAccessible(true);
            field.set(null, value);
            field.setAccessible(false);
        }
    }
}
